﻿using System;
using TK.FreeSqlExtension;

namespace FreeSql
{
    /// <summary>
    /// MultiFreeSqlExtensions
    /// </summary>
    public static class MultiFreeSqlExtensions
    {
        /// <summary>
        /// 多freesql切换
        /// </summary>
        /// <typeparam name="TDBKey">数据库唯一标识类型</typeparam>
        /// <param name="fsql">MultiFreeSql或其泛型</param>
        /// <param name="dbkey">数据库唯一标识</param>
        public static IFreeSql ChangeDatabaseByKey(this IFreeSql fsql, string dbkey)
        {
            if (string.IsNullOrWhiteSpace(dbkey))
            {
                throw new ArgumentNullException(nameof(dbkey));
            }

            if (!(fsql is MultiFreeSql multiFsql))
            {
                throw new Exception("fsql 类型不是 MultiFreeSql");
            }

            multiFsql.SplitInfo.Value = new SplitInfo { DbKey = dbkey };
            return multiFsql;
        }

        /// <summary>
        /// 多freesql切换,使用完Dispose后，切换回原来数据库
        /// </summary>
        /// <typeparam name="TDBKey">数据库唯一标识类型</typeparam>
        /// <param name="fsql">MultiFreeSql或其泛型</param>
        /// <param name="dbkey">数据库唯一标识</param>
        public static IDisposable Change(this IFreeSql fsql, string dbkey)
        {
            if (string.IsNullOrWhiteSpace(dbkey))
            {
                throw new ArgumentNullException(nameof(dbkey));
            }

            if (!(fsql is MultiFreeSql multiFsql))
            {
                throw new Exception("fsql 类型不是 MultiFreeSql");
            }

            var olddbkey = multiFsql.SplitInfo.Value?.DbKey;
            multiFsql.ChangeDatabaseByKey(dbkey);
            return new DBChangeDisposable(() => multiFsql.ChangeDatabaseByKey(olddbkey));
        }

        /// <summary>
        /// 注册freesql
        /// </summary>
        /// <typeparam name="TDBKey">数据库唯一标识类型</typeparam>
        /// <param name="fsql">MultiFreeSql或其泛型</param>
        /// <param name="dbkey">数据库唯一标识</param>
        /// <param name="create">真实freesql函数,切记freesql对象不要引用外部对象变量</param>
        public static IFreeSql Register(this IFreeSql fsql, string dbkey, Func<IFreeSql> create)
        {
            if (string.IsNullOrWhiteSpace(dbkey))
            {
                throw new ArgumentNullException(nameof(dbkey));
            }

            if (!(fsql is MultiFreeSql multiFsql))
            {
                throw new Exception("fsql 类型不是 MultiFreeSql");
            }

            if (multiFsql._ib.TryRegister(dbkey, create))
                if (multiFsql._ib.GetKeys().Length == 1)
                    multiFsql._dbkeyMaster = dbkey;
            return multiFsql;
        }
    }

    /// <summary>
    /// DBChangeDisposable
    /// </summary>
    class DBChangeDisposable : IDisposable
    {
        readonly Action _cancel;

        /// <summary>
        /// ctor
        /// </summary>
        public DBChangeDisposable(Action cancel) => _cancel = cancel;

        /// <summary>
        /// dispose
        /// </summary>
        public void Dispose() => _cancel?.Invoke();
    }
}
